var _ = require('lodash'),
    Q = require('q'),
    PublicEnum = require('../../../Base/server/controllers/Enum'),
    BarcodeEnum = require('../../../Barcode/server/controllers/Enum.server.controller'),
    QCEnum = require('../../../QC/server/controllers/Enum.server.controller'),
    barcodeMasterController = require('../../../Barcode/server/controllers/BarcodeMaster.server.controller'),
    operationController = require('../../../CBO/server/controllers/Operation.server.controller'),
    Transaction = require('../../../Base/server/controllers/Transaction'),
    wareHouseController = require('../../../CBO/server/controllers/WareHouse.server.controller'),
    rcvRecordController = require('../../../ProduceWork/server/controllers/RcvRecord.server.controller');

exports.scanCode = function (req, res) {
    var parameter = req.body,
        barcode = parameter.Barcode;

    var bindContext = {
        Work: parameter.WorkId,
        WorkName: parameter.WorkName,
        User: parameter.UserId,
        WorkLocation: parameter.WorkLocationId,
        WorkLocationName: parameter.WorkLocationName
    }, barcodeMaster;

    queryBarcodeMaster(barcode).then(function (record) {
        barcodeMaster = record;
        return queryOperation(barcodeMaster, bindContext.Work);
    }).then(function (operation) {
        return barcodeMasterController.streamValidation(barcodeMaster, operation, bindContext);
    }).then(function () {
        var result = {
            Barcode: barcodeMaster.Barcode,
            MOCode: barcodeMaster.MOCode,
            MOLotNumber: barcodeMaster.MOLotNumber,
            ItemMasterCode: barcodeMaster.ItemMasterCode,
            ItemMasterName: barcodeMaster.ItemMasterName,
            Specification: barcodeMaster.Specification,
            WorkName: barcodeMaster.WorkName
        };
        res.json({
            Data: result,
            Error: null
        });
    }).catch(function (err) {
        res.json({
            Data: null,
            Error: err
        });
    })
    .done();
};

exports.submit = function (req, res) {
    var parameter = req.body,
        barcodes = parameter.Barcodes,
        department = parameter.Department;

    if (_.isString(barcodes)) {
        barcodes = [barcodes];
    }
    
    var baseInfo = {
        Terminal: parameter.TerminalId,
        TerminalName: parameter.TerminalName,
        Work: parameter.WorkId,
        WorkName: parameter.WorkName,
        Users: [parameter.UserId],
        WorkLocation: parameter.WorkLocationId,
        WorkLocationName: parameter.WorkLocationName,
        QCType: QCEnum.QCType.FullReview,
        QCDateTime: Date.now(),
        QCStatus: QCEnum.QCStatus.Qualified
    }, barcodeMasters, _operation;

    barcodeMasterController.findBarcodeMasters(barcodes).then(function (records) {
        if (!records || records.length === 0) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '无法识别条码';
            newErr.message = '无法识别的条码，请重新扫描！';
            deferred.reject(newErr);
            return;
        }
        barcodeMasters = records;
        return queryOperation(barcodeMasters[0], baseInfo.Work);
    }).then(function (operation) {
        _operation = operation;
        var bindContext = { User: parameter.UserId };
        _.merge(bindContext, baseInfo);
        return barcodeMasterController.streamValidation(barcodeMasters, operation, bindContext);
    }).then(function () {
        return updateBizData(barcodeMasters, baseInfo);
    }).then(function () {
        if (_operation && _operation.IsStoragePoint) {
            return addStockQty(barcodeMasters, parameter.UserId, department);
        } else {
            return Q.resolve();
        }
    }).then(function () {
        res.json({
            Data: true,
            Error: null
        });
    }, function (err) {
        res.json({
            Data: null,
            Error: err
        });
    });
};

function queryBarcodeMaster (barcode) {
    var deferred = Q.defer();
    
    barcodeMasterController.findBarcodeMaster(barcode, function (err, barcodeMasterRecord) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (barcodeMasterRecord == null) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '无法识别条码';
            newErr.message = '无法识别的条码，请重新扫描！';
            deferred.reject(newErr);
            return;
        }
        if (barcodeMasterRecord.BarcodeType !== BarcodeEnum.BarcodeType.ItemMaster) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '非法条码';
            newErr.message = '条码类型不是物料，请重新扫描！';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve(barcodeMasterRecord);
    });

    return deferred.promise;
}

function updateBizData (barcodeMasters, baseInfo) {
    var deferred = Q.defer();

    var bizRecords = [],
        updateBarcodeMasters = [],
        batches = [];
    _.forEach(barcodeMasters, function (barcodeMaster) {
        var tbizRecord = {
            RowStatus: PublicEnum.RowStatus.Insert,
            CreatedBy: baseInfo.Users[0],
            CollectDateTime: baseInfo.QCDateTime,
            QCUser: baseInfo.Users[0],
            BarcodeMaster: barcodeMaster._id
        };
        _.merge(tbizRecord, baseInfo);
        bizRecords.push(tbizRecord);

        var tBarcodeMaster = {
            RowStatus: PublicEnum.RowStatus.Modify,
            CreatedBy: baseInfo.Users[0],
            _id: barcodeMaster._id
        };
        _.merge(tBarcodeMaster, baseInfo);
        updateBarcodeMasters.push(tBarcodeMaster);

        batches.push(queryOperationTag(barcodeMaster, baseInfo.Work, tbizRecord, tBarcodeMaster));
    });
    Q.all(batches).then(function () {
        Transaction.BatchSaveByTran([
            { EntityName: 'BizRecord', Records: bizRecords },
            { EntityName: 'BarcodeMaster', Records: updateBarcodeMasters },
        ], function(err, result){
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve(result);
        });
    }, function () {
        var newErr = new Error();
        newErr.leval = 9;
        newErr.message = '查询工序失败';
        deferred.reject(newErr);
    });

    return deferred.promise;
}

function queryOperation (barcodeMaster, work) {
    var deferred = Q.defer();
    
    if (!barcodeMaster.ItemMaster) {
        var newErr = new Error();
        newErr.leval = 9;
        newErr.message = '主档未绑定物料';
        deferred.reject(newErr);
        return;
    }
    operationController.findByItemMasterAndWork(barcodeMaster.ItemMaster._id, work, function (err, result) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!result) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '非法数据';
            newErr.message = '没有找到对应的工序';
            deferred.reject(newErr);
            return;
        }
        deferred.resolve(result);
    });

    return deferred.promise;
}

function queryOperationTag (barcodeMaster, work, tbizRecord, tbarcodeMaster) {
    var deferred = Q.defer();
    
    if (!barcodeMaster.ItemMaster) {
        var newErr = new Error();
        newErr.leval = 9;
        newErr.message = '主档未绑定物料';
        deferred.reject(newErr);
        return;
    }
    operationController.findByItemMasterAndWork(barcodeMaster.ItemMaster._id, work, function (err, result) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!result) {
            deferred.resolve();
            return;
        }
        _.merge(tbizRecord, {
            Operation: result._id,
            OperationName: result.Name
        });
        _.merge(tbarcodeMaster, {
            Operation: result._id,
            OperationName: result.Name
        });
        deferred.resolve();
    });

    return deferred.promise;
}

function addStockQty (barcodeMasters, userId, department) {
    var deferred = Q.defer();

    wareHouseController.findByDepartment(department).then(function (wareHouse) {
        if (!wareHouse) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询仓库';
            newErr.message = '没有找到对应的仓库';
            deferred.reject(newErr);
            return;
        }
        var stockQties = [],
        stockBatches = [];
        _.forEach(barcodeMasters, function (barcodeMaster) {
            stockBatches.push({
                BarcodeMaster: barcodeMaster._id,
                Barcode: barcodeMaster.Barcode,
                ItemMaster: barcodeMaster.ItemMaster ? barcodeMaster.ItemMaster._id : null,
                DescSeg1: barcodeMaster.DescSeg1,
                DescSeg2: barcodeMaster.DescSeg2,
                BusinessDocID: barcodeMaster.MO ? barcodeMaster.MO._id : null,
                RcvUser: userId,
                RcvOperation: barcodeMaster.Operation ? barcodeMaster.Operation._id : null,
                BizRecord: barcodeMaster.BizRecord ? barcodeMaster.BizRecord._id : null,
                WareHouse: wareHouse._id
            });
        });
        if (stockBatches.length === 0) {
            deferred.resolve();
        } else {
            rcvRecordController.addStockQty(stockBatches).then(function () {
                deferred.resolve();
            }, function (err) {
                deferred.reject(err);
            });
        }
    });

    return deferred.promise;
}